package com.southgis.ibase.sql.builder;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
import java.util.function.Consumer;

import org.apache.commons.lang3.tuple.MutablePair;

import com.southgis.ibase.sql.builder.ClauseItem.AndCond;
import com.southgis.ibase.sql.builder.ClauseItem.BoolCond;
import com.southgis.ibase.sql.builder.ClauseItem.CaseValue;
import com.southgis.ibase.sql.builder.ClauseItem.CollectionValue;
import com.southgis.ibase.sql.builder.ClauseItem.ConstantValue;
import com.southgis.ibase.sql.builder.ClauseItem.ExpressionCond;
import com.southgis.ibase.sql.builder.ClauseItem.FieldValue;
import com.southgis.ibase.sql.builder.ClauseItem.FunctionValue;
import com.southgis.ibase.sql.builder.ClauseItem.NotCond;
import com.southgis.ibase.sql.builder.ClauseItem.OrCond;
import com.southgis.ibase.sql.builder.ClauseItem.ParamValue;
import com.southgis.ibase.sql.builder.ClauseItem.SegmentValue;
import com.southgis.ibase.sql.builder.ClauseItem.SingleValue;
import com.southgis.ibase.sql.builder.SqlBuilder.DeleteSqlBuilder;
import com.southgis.ibase.sql.builder.SqlBuilder.InsertSqlBuilder;
import com.southgis.ibase.sql.builder.SqlBuilder.SelectSqlBuilder;
import com.southgis.ibase.sql.builder.SqlBuilder.UpdateSqlBuilder;
import com.southgis.ibase.sql.enums.FuncDefine;
import com.southgis.ibase.sql.exception.SQLAnalyseException;

/**
 * sql子句构造器，字段信息、常量、函数调用、计算式、逻辑表达式等都使用“子句”描述。<br>
 * 其中，字段信息、常量、函数调用、计算式，又称“单项值”子句
 * @author dnnyo
 *
 */
public class ClauseBuilder
{
	/**
	 * 改变优先级的占位节点，相当于左括号
	 */
	private static final Object TOKEN_GROUP_BEGIN=new Object();
	/**
	 * 改变优先级的占位节点，相当于右括号
	 */
	private static final Object TOKEN_GROUP_END=new Object();
	/**
	 * 占位节点:not
	 */
	private static final Object TOKEN_NOT=new Object();
	/**
	 * 占位节点:and
	 */
	private static final Object TOKEN_AND=new Object();
	/**
	 * 占位节点:or
	 */
	private static final Object TOKEN_OR=new Object();
	/**
	 * 函数开始调用占位节点。结构如下：<br>
	 * [TOKEN_FUNC] prev_value optor funcName arg...
	 */
	private static final Object TOKEN_FUNC=new Object();
	/**
	 * CASE语句开始占位节点，内部各元素使用其他占位节点分隔。结构如下：<br>
	 * [TOKEN_CASE] prev_value optor [TOKEN_AND] fld<br>
	 *  [TOKEN_GROUP_BEGIN] when [TOKEN_OR] then<br>
	 *  [TOKEN_GROUP_BEGIN] when [TOKEN_OR] then<br>
	 *  [TOKEN_GROUP_END] else<br>
	 */
	private static final Object TOKEN_CASE=new Object();
	
	/**
	 * 构造函数调用过程的缓存
	 */
	Stack<Object> funcBuildCache=new Stack<>();
	/**
	 * 构造case子句过程的缓存
	 */
	Stack<Object> caseBuildCache=new Stack<>();
	/**
	 * 逻辑运算节点
	 */
	Stack<Object> groupNodes=new Stack<>();
	//正在处理表达式操作符
	String exprOperator="";
	//当前正在处理表达式项
	ClauseItem current;
	
	/**
	 * 嵌入在SqlBuilder中的条件构造中，完成时要用这些信息返回。
	 * 类型有：SelectSqlBuilder/DeleteSqlBuilder/UpdateSqlBuilder/InsertSqlBuilder
	 */
	Object parent;
	Consumer<ClauseItem> callback;
	
	ClauseBuilder()
	{
	}
	
	/**
	 * 在嵌入SelectSqlBuilder/DeleteSqlBuilder/UpdateSqlBuilder/InsertSqlBuilder中的条件构造，
	 * 需要使用over()返回到SqlBuilder中
	 * @param parent
	 * @param callback
	 */
	ClauseBuilder(Object parent, Consumer<ClauseItem> callback)
	{
		this.parent=parent;
		this.callback=callback;
	}
	/**
	 * 重置内部状态，可重新构建条件
	 */
	public ClauseBuilder reset()
	{
		current=null;
		exprOperator="";
		groupNodes.clear();
		funcBuildCache.clear();
		caseBuildCache.clear();
		
		return this;
	}
	
	/**
	 * 产生一个新的条件构造器。每次调用创建一个对象，因此线程安全
	 * @return
	 */
	public static ClauseBuilder produce()
	{
		return new ClauseBuilder();
	}
	
	/**
	 * 在构造函数条件时，需要获取当前节点为参数时，可通过此方法获取
	 * @return
	 */
	public ClauseItem getCurrent()
	{
		return current;
	}

	/**
	 * 将常量值转换为参数表达式或常量表达式。BoolCondition类型不支持转换
	 * @param value 查询参数、常量（特殊说明参见{@link #eq(Object)}）、SingleValue对象
	 * @return
	 */
	public static SingleValue valueToCond(Object value)
	{
		SingleValue right=null;
		if(value!=null) {
			if(value instanceof SingleValue)
				right=(SingleValue)value;
			else if(value instanceof TableColumn) {
				right=new FieldValue((TableColumn)value);
			}else if(value instanceof SelectSqlBuilder) {
				right=new FieldValue(value, "");
			}else if(value instanceof BoolCond) {
				throw new SQLAnalyseException("不能转换 BoolCondition类型的值为SingleValue类型");
			}
			else if((value instanceof String) && !((String)value).isEmpty()) {
				String temp=(String)value;
				char chx=temp.charAt(0);
				if(chx=='?' || chx==':') {
					right = new ParamValue(temp);
				} else if(chx=='`' && temp.charAt(temp.length()-1)=='`') {
					value=temp.substring(1,temp.length()-1);
				}
			}
			
		}
		
		if(right==null)
			right=new ConstantValue(value);

		return right;
	}

	//----region:辅助方法-------------------------------
	//处理表达式右值
	private void dealExpress(ClauseItem right)
	{
		if(exprOperator.isEmpty()) {
			current=right;
		}else {
			current=new ExpressionCond(current, exprOperator, right);
			exprOperator="";
		}
	}
	//直接处理表达式右值，忽略之前的比较符
	private void dealExpress(String optor, ClauseItem right)
	{
		current=new ExpressionCond(current, optor, right);
		exprOperator="";
	}

	//README 单项值----
	/**
	 * 构造查询参数项
	 * @return
	 */
	public ClauseBuilder param()
	{
		dealExpress(new ParamValue("?"));
		return this;
	}
	/**
	 * 构造有序号的查询参数项
	 * @param inx
	 * @return
	 */
	public ClauseBuilder param(int inx)
	{
		dealExpress(new ParamValue("?"+inx));
		return this;
	}
	/**
	 * 构造查询参数项
	 * @param pmName 参数名，以:开头
	 * @return
	 */
	public ClauseBuilder param(String pmName)
	{
		if(pmName.charAt(0)!=':')
			pmName=":"+pmName;
		dealExpress(new ParamValue(pmName));
		return this;
	}
	
	/**
	 * 构造常量项，如果是字符串常量，不需要添加单引号（内部自动添加）
	 * @param value
	 * @return
	 */
	public ClauseBuilder c(Object value)
	{
		dealExpress(new ConstantValue(value));
		return this;
	}
	/**
	 * 构造集合值（包括SqlTable、Collection、Array）
	 * @param value
	 * @return
	 */
	public ClauseBuilder collection(Object value)
	{
		dealExpress(new CollectionValue(value));
		return this;
	}
	
	/**
	 * 构造字段项
	 * @param value
	 * @return
	 */
	public ClauseBuilder field(TableColumn value)
	{
		dealExpress(new FieldValue(value));
		return this;
	}
	/**
	 * 构造字段项
	 * @param tbl
	 * @param fld
	 * @return
	 */
	public ClauseBuilder field(Table tbl, String fld)
	{
		return field(new TableColumn(tbl, fld, null));
	}
	public ClauseBuilder field(String fld)
	{
		return field(new TableColumn((Table)null, fld, null));
	}
	/**
	 * 基于表名（或本身就是别名），构建一个表字段描述
	 * @param tblName
	 * @param fld
	 * @return
	 */
	public ClauseBuilder field(String tblName, String fld)
	{
		return field(new TableColumn(tblName, fld, null));
	}

//	/**
//	 * 将当前表达式做为字段
//	 * @param alias
//	 * @return
//	 */
//	public ClauseBuilder asfield(String alias)
//	{
//		dealExpress(new FieldValue(current, alias));
//		return this;
//	}
	
	//====region:单项值===============================

	//README region:函数调用（计算）项----
	/**
	 * 构造一个函数调用项
	 * @param func
	 * @param params
	 * @return
	 */
	public ClauseBuilder function(String func, Object... params)
	{
		dealExpress(new FunctionValue(func, params));
		return this;
	}
	/**
	 * 开始构造一个函数调用，各参数可独立构造，并在每个参数构造完成后用to_farg()依次置为函数所参数。
	 * 所有参数构造完成后，用funcEnd()结束
	 * @param func 函数名，内部处理一些通用命名，对于未预定义的名字，原样输出（未考虑跨库差异）
	 * @return
	 */
	public ClauseBuilder funcBegin(String func)
	{
		funcBuildCache.push(TOKEN_FUNC);
		funcBuildCache.push(current);
		funcBuildCache.push(exprOperator);
		funcBuildCache.push(func);
		
		current=null;
		exprOperator="";
		return this;
	}
	/**
	 * 从funcBegin/to_farg到本次调用之间生成的结果转换为函数参数
	 * @return
	 */
	public ClauseBuilder to_farg()
	{
		funcBuildCache.push(current);
		
		current=null;
		exprOperator="";
		return this;
	}
	/**
	 * 将当前值设为funcBegin所指明函数的一个参数
	 * @param val
	 * @return
	 */
	public ClauseBuilder farg(Object val)
	{
		funcBuildCache.push(valueToCond(val));
		return this;
	}
	/**
	 * 结束函数构造，与funcBegin成对出现
	 * @return
	 */
	public ClauseBuilder funcEnd()
	{
		//生成一个函数调用
		Stack<Object> next=new Stack<>();
		while(!funcBuildCache.empty()) {
			Object item=funcBuildCache.pop();
			if(item==TOKEN_FUNC) {
				current=(ClauseItem)next.pop();
				exprOperator=(String)next.pop();
				String funcName=(String)next.pop();
				Object[] args=new Object[next.size()];
				int inx=0;
				while(!next.empty()) {
					args[inx++]=next.pop();
				}
				function(funcName, args);
				
				if(!funcBuildCache.empty()) {
					to_farg();
				}
				break;
			}
			next.push(item);
		}
		if(!next.empty()) {
			throw new SQLAnalyseException("构造函数调用语句不正确，这些节点未正确匹配："+next.toString());
		}

		return this;
	}
	
	
	/**
	 * 生成分组排序的行号结果：ROW_NUMBER() OVER(ORDER BY fld desc)
 * @param orderFld 排序字段，如果为空，则不排序
	 * @param desc 排序方式是否降序
	 * @return
	 */
	public ClauseBuilder rownum(Object orderFld, boolean desc)
	{
		return rownum(null, orderFld, desc);
	}
	
	/**
	 * 生成分组排序的行号结果：ROW_NUMBER() OVER(PARTITION BY fld ORDER BY fld desc)
	 * @param partitionFld 分组字段，如果为空，则不分组
	 * @param orderFld 排序字段，如果为空，则不排序
	 * @param desc 排序方式是否降序
	 * @return
	 */
	public ClauseBuilder rownum(Object partitionFld, Object orderFld, boolean desc)
	{
		SegmentValue seg=new SegmentValue();
		seg.addBracketBlock("ROW_NUMBER");
		SegmentValue block=seg.addBracketBlock("OVER");
		if(partitionFld!=null)
			block.add("PARTITION BY").add(valueToCond(partitionFld));
		if(orderFld!=null) {
			block.add("ORDER BY").add(valueToCond(orderFld)).add(desc?"ASC":"DESC");
		}
		
		dealExpress(seg);
		return this;
	}
	
	/**
	 * 类型转换
	 * @param value 转换前的值（子句、表字段对象、常量值
	 * @param type 转换后的类型，java.sql.Types定义值
	 * @return
	 */
	public ClauseBuilder cast(Object value, int type)
	{
		SingleValue sv=new FunctionValue(FuncDefine.CAST, value, type);
		dealExpress(sv);
		return this;

	}
	
	/**
	 * 空则用other值，这个函数，不同数据库不一样：
	 * oralce--nvl,postgresql--COALESCE,mysql--ifnull
	 * @param value
	 * @param other
	 * @return
	 */
	public ClauseBuilder ifnull(Object value, Object other)
	{
		SingleValue sv=new FunctionValue(FuncDefine.IFNULL, value, other);
		dealExpress(sv);
		return this;
	}
	
	/**
	 * 开始case语句构造，每一段由to_cwhen/cwhen与to_cthen/cthen组成，
	 * 有其他段时，调用to_celse/celse添加；
	 * 最后调用caseEnd结束构造
	 * @return
	 */
	public ClauseBuilder caseBegin()
	{
		caseBuildCache.push(TOKEN_CASE);
		caseBuildCache.push(current);
		caseBuildCache.push(exprOperator);
		
		current=null;
		exprOperator="";
		return this;
		
	}
	/**
	 * 从caseBegin到本次调用之间生成的结果转换为case与when间的判断字段（判断字段可省略）
	 * @return
	 */
	public ClauseBuilder to_cfield()
	{
		if(current==null || !(current instanceof FieldValue))
			return this;
		
		caseBuildCache.push(TOKEN_AND);
		caseBuildCache.push(((FieldValue)current).getValue());
		
		current=null;
		exprOperator="";
		return this;
	}
	/**
	 * 将表达式设为case的判断字段（判断字段可省略）
	 * @param fld
	 * @return
	 */
	public ClauseBuilder cfield(TableColumn fld)
	{
		caseBuildCache.push(TOKEN_AND);
		caseBuildCache.push(fld);
		
		return this;
	}
	/**
	 * 将表字段对象设为case的判断字段（判断字段可省略）
	 * @param fld
	 * @return
	 */
	public ClauseBuilder cfield(Table tbl, String fld)
	{
		return cfield(new TableColumn(tbl, fld, null));
	}
	/**
	 * 将表字段对象设为case的判断字段（判断字段可省略）
	 * @param fld
	 * @return
	 */
	public ClauseBuilder cfield(String fld)
	{
		return cfield(new TableColumn((Table)null, fld, null));
	}
	/**
	 * 将表字段对象设为case的判断字段（判断字段可省略）
	 * @param tblName
	 * @param fld
	 * @return
	 */
	public ClauseBuilder cfield(String tblName, String fld)
	{
		return cfield(new TableColumn(tblName, fld, null));
	}
	
	/**
	 * 从caseBegin/to_cfield/to_cthen到本次调用之间生成的结果转换为case的when条件值
	 * @return
	 */
	public ClauseBuilder to_cwhen()
	{
		caseBuildCache.push(TOKEN_GROUP_BEGIN);
		caseBuildCache.push(current);
		
		current=null;
		exprOperator="";
		return this;
	}
	/**
	 * 将指定值转换为case的when条件值
	 * @return
	 */
	public ClauseBuilder cwhen(Object val)
	{
		caseBuildCache.push(TOKEN_GROUP_BEGIN);
		if(val instanceof BoolCond) {
			caseBuildCache.push(val);
		}else {
			caseBuildCache.push(valueToCond(val));
		}
		
		return this;
	}
	/**
	 * 从to_cwhen到本次调用之间生成的结果转换为case的then返回结果
	 * @return
	 */
	public ClauseBuilder to_cthen()
	{
		caseBuildCache.push(TOKEN_OR);
		caseBuildCache.push(current);
		
		current=null;
		exprOperator="";
		return this;
	}
	/**
	 * 将指定值转换为case的then返回结果
	 * @return
	 */
	public ClauseBuilder cthen(Object val)
	{
		caseBuildCache.push(TOKEN_OR);
		caseBuildCache.push(valueToCond(val));
		
		return this;
	}
	/**
	 * 从caseBegin/to_cthen到本次调用之间生成的结果转换为函数参数<br>
	 * 如果没有调用to_cwhen，则默认条件为name is not null；<br>
	 * 如果也没调用to_cthen，则默认值为原值<br>
	 * 以上简化相当于函数：oracle的NVL(name,celse)
	 * @return
	 */
	public ClauseBuilder to_celse()
	{
		caseBuildCache.push(TOKEN_GROUP_END);
		caseBuildCache.push(current);
		
		current=null;
		exprOperator="";
		return this;
	}
	/**
	 * 将指定值转为case的else返回值。
	 * @see #to_celse()
	 * @param val
	 * @return
	 */
	public ClauseBuilder celse(Object val)
	{
		caseBuildCache.push(TOKEN_GROUP_END);
		caseBuildCache.push(valueToCond(val));
		
		return this;
	}
	
	/**
	 * 完成case的构建，与caseBegin成对
	 * @return
	 */
	public ClauseBuilder caseEnd()
	{
		TableColumn col=null;
		List<MutablePair<Object, Object>> caseWhen=new ArrayList<>();
		Object caseElse=null;

		//生成一个值转换:CASE prev_value optor AND fld BEGIN when OR then BEGIN w OR t END else
		Stack<Object> next=new Stack<>();
		while(!caseBuildCache.empty()) {
			Object item=caseBuildCache.pop();
			if(item==TOKEN_CASE) {
				current=(ClauseItem)next.pop();
				exprOperator=(String)next.pop();
				
				Collections.reverse(caseWhen);
				dealExpress(new CaseValue(col,caseWhen,caseElse));
				
				break;
			}else if(item==TOKEN_GROUP_END) {
				caseElse=next.pop();
			}else if(item==TOKEN_OR) {
				caseWhen.add(MutablePair.of(null,next.pop()));
			}else if(item==TOKEN_GROUP_BEGIN) {
				caseWhen.get(caseWhen.size()-1).setLeft(next.pop());
			}else if(item==TOKEN_AND) {
				col=(TableColumn)next.pop();
			}else {
				next.push(item);
			}
		}
		if(!next.empty()) {
			throw new SQLAnalyseException("构造case语句不正确，这些节点未正确匹配："+next.toString());
		}
		
		return this;
	}
	
	
	//====region:计算项===============================
	
	//README region:条件判断----
	/**
	 * 等于后面构造的项。
	 * @see #eq(Object)
	 * @return
	 */
	public ClauseBuilder eq()
	{
		exprOperator="=";
		return this;
	}
	/**
	 * 等于指定值
	 * @param paramOrValue 如果以?开头，或以:开头，表示查询参数。如果将此视为常量，则需要用右单引号包含。<br>
	 * 即：如果以`?、`:、?、:开头的字符串常量，需要用右单引号包含。如：<br>
	 * `?询问提示`、`:你好`、``:这就是`abc`
	 * @return
	 */
	public ClauseBuilder eq(Object paramOrValue)
	{
		dealExpress("=", valueToCond(paramOrValue));
		return this;
	}
	/**
	 * 等于表字段
	 * @param tbl
	 * @param fld
	 * @return
	 */
	public ClauseBuilder eq(Table tbl, String fld)
	{
		dealExpress("=", new FieldValue(tbl.column(fld,null)));
		return this;
	}
	/**
	 * 不等于后面构造的项。
	 * @return
	 */
	public ClauseBuilder ne()
	{
		exprOperator="<>";
		return this;
	}
	/**
	 * 不等于指定值
	 * @see #eq(Object)
	 * @param paramOrValue
	 * @return
	 */
	public ClauseBuilder ne(Object paramOrValue)
	{
		dealExpress("<>", valueToCond(paramOrValue));
		return this;
	}
	/**
	 * 不等于表字段
	 * @param tbl
	 * @param fld
	 * @return
	 */
	public ClauseBuilder ne(Table tbl, String fld)
	{
		dealExpress("<>", new FieldValue(tbl.column(fld,null)));
		return this;
	}
	/**
	 * 大于后面构造的项
	 * @return
	 */
	public ClauseBuilder gt()
	{
		exprOperator=">";
		return this;
	}
	/**
	 * 大于指定的值
	 * @see #eq(Object)
	 * @param paramOrValue
	 * @return
	 */
	public ClauseBuilder gt(Object paramOrValue)
	{
		dealExpress(">", valueToCond(paramOrValue));
		return this;
	}
	/**
	 * 大于表字段
	 * @param tbl
	 * @param fld
	 * @return
	 */
	public ClauseBuilder gt(Table tbl, String fld)
	{
		dealExpress(">", new FieldValue(tbl.column(fld,null)));
		return this;
	}
	/**
	 * 大于等于后面构造的项
	 * @return
	 */
	public ClauseBuilder gte()
	{
		exprOperator=">=";
		return this;
	}
	/**
	 * 大于等于指定的值
	 * @see #eq(Object)
	 * @param paramOrValue
	 * @return
	 */
	public ClauseBuilder gte(Object paramOrValue)
	{
		dealExpress(">=", valueToCond(paramOrValue));
		return this;
	}
	/**
	 * 大于等于表字段
	 * @param tbl
	 * @param fld
	 * @return
	 */
	public ClauseBuilder gte(Table tbl, String fld)
	{
		dealExpress(">=", new FieldValue(tbl.column(fld,null)));
		return this;
	}
	/**
	 * 小于后面构造的项
	 * @return
	 */
	public ClauseBuilder lt()
	{
		exprOperator="<";
		return this;
	}
	/**
	 * 小于指定的值
	 * @see #eq(Object)
	 * @param paramOrValue
	 * @return
	 */
	public ClauseBuilder lt(Object paramOrValue)
	{
		dealExpress("<", valueToCond(paramOrValue));
		return this;
	}
	/**
	 * 小于字段
	 * @param tbl
	 * @param fld
	 * @return
	 */
	public ClauseBuilder lt(Table tbl, String fld)
	{
		dealExpress("<", new FieldValue(tbl.column(fld,null)));
		return this;
	}
	/**
	 * 小于等于后面构造的项
	 * @return
	 */
	public ClauseBuilder lte()
	{
		exprOperator="<=";
		return this;
	}
	/**
	 * 小于等于指定的值
	 * @see #eq(Object)
	 * @param paramOrValue
	 * @return
	 */
	public ClauseBuilder lte(Object paramOrValue)
	{
		dealExpress("<=", valueToCond(paramOrValue));
		return this;
	}
	/**
	 * 小于等于表字段
	 * @param tbl
	 * @param fld
	 * @return
	 */
	public ClauseBuilder lte(Table tbl, String fld)
	{
		dealExpress("<=", new FieldValue(tbl.column(fld,null)));
		return this;
	}
	/**
	 * like比较后面构造的项
	 * @return
	 */
	public ClauseBuilder like()
	{
		exprOperator=" like ";
		return this;
	}
	/**
	 * like 条件
	 * @param value 比较值，需要包含通匹符，但不需要包含单引号
	 * @return
	 */
	public ClauseBuilder like(String value)
	{
		dealExpress(" like ", new ConstantValue(value));
		return this;
	}
	/**
	 * not like比较后面构造的项
	 * @return
	 */
	public ClauseBuilder notlike()
	{
		exprOperator=" not like ";
		return this;
	}
	/**
	 * not like 条件
	 * @param value 比较值，需要包含通匹符，但不需要包含单引号
	 * @return
	 */
	public ClauseBuilder notlike(String value)
	{
		dealExpress(" not like ", new ConstantValue(value));
		return this;
	}
	/**
	 * in 包含后面构造的项（集合）
	 * @return
	 */
	public ClauseBuilder in()
	{
		exprOperator=" in ";
		return this;
	}
	/**
	 * in sql值的条件
	 * @param tbl
	 * @return
	 */
	public ClauseBuilder in(SelectSqlBuilder tbl)
	{
		dealExpress(" in ", new CollectionValue(tbl));
		return this;
	}
	/**
	 * in 条件
	 * @param values
	 * @return
	 */
	public ClauseBuilder in(Object... values)
	{
		dealExpress(" in ", new CollectionValue(values));
		return this;
	}
	/**
	 * not in 包含后面构造的项（集合）
	 * @return
	 */
	public ClauseBuilder notin()
	{
		exprOperator=" not in ";
		return this;
	}
	/**
	 * not in sql值的条件
	 * @param tbl
	 * @return
	 */
	public ClauseBuilder notin(SelectSqlBuilder tbl)
	{
		dealExpress(" not in ", new CollectionValue(tbl));
		return this;
	}
	/**
	 * not in 条件
	 * @param values
	 * @return
	 */
	public ClauseBuilder notin(Object... values)
	{
		dealExpress(" not in ", new CollectionValue(values));
		return this;
	}
	/**
	 * 查询结果是否存在 判断
	 * @param tbl
	 * @return
	 */
	public ClauseBuilder exists(SelectSqlBuilder tbl)
	{
		dealExpress(" exists ", new CollectionValue(tbl));
		return this;
	}
	/**
	 * 查询结果是否不存在 判断
	 * @param tbl
	 * @return
	 */
	public ClauseBuilder notexists(SelectSqlBuilder tbl)
	{
		dealExpress(" not exists ", new CollectionValue(tbl));
		return this;
	}
	/**
	 * 前一个值是否为null
	 * @return
	 */
	public ClauseBuilder isnull()
	{
		current = new ExpressionCond(current, " is ", new ConstantValue(null));
		exprOperator="";
		return this;
	}
	/**
	 * 前一个值是否为not null
	 * @return
	 */
	public ClauseBuilder isnotnull()
	{
		current = new ExpressionCond(current, " is not ", new ConstantValue(null));
		exprOperator="";
		return this;
	}
	

//	public ConditionBuilder expression(String opt)
//	{
//		prev=current;
//		prevType=1;
//		current=null;
//		//new ExpressionCond(left, opt, right);
//		return this;
//	}
	//====region:条件判断===============================

	//README region:逻辑组合----

	/**
	 * 将后面构造的逻辑结果取反（真变假、假变真）
	 * @return
	 */
	public ClauseBuilder not()
	{
		groupNodes.push(TOKEN_NOT);
		exprOperator="";
		return this;
	}
	/**
	 * 将前面构造的逻辑结果 与 后面构造的逻辑结果 and组合
	 * @return
	 */
	public ClauseBuilder and()
	{
		groupNodes.push(current);
		groupNodes.push(TOKEN_AND);
		current=null;
		exprOperator="";
		return this;
	}
	/**
	 * 将前面构造的逻辑结果 与 后面构造的逻辑结果 or组合
	 * @return
	 */
	public ClauseBuilder or()
	{
		groupNodes.push(current);
		groupNodes.push(TOKEN_OR);
		current=null;
		exprOperator="";
		return this;
	}
	
	/**
	 * 逻辑优先组合，相当于左括号
	 * @return
	 */
	public ClauseBuilder groupBegin()
	{
		groupNodes.push(TOKEN_GROUP_BEGIN);
		exprOperator="";
		return this;
	}
	/**
	 * 一组逻辑优先组合结束，相当于右括号
	 * @return
	 */
	public ClauseBuilder groupEnd()
	{
		groupNodes.push(current);
		groupNodes.push(TOKEN_GROUP_END);
		current=null;
		exprOperator="";
		return this;
	}
	//====region:逻辑组合===============================


	/**
	 * 完成当前内嵌构造，返回到SelectSqlBuilder构造
	 * @return
	 */
	public SelectSqlBuilder toSel()
	{
		over();
		return (SelectSqlBuilder)parent;
	}
	/**
	 * 完成当前内嵌构造，返回到DelectSqlBuilder构造
	 * @return
	 */
	public DeleteSqlBuilder toDel()
	{
		over();
		return (DeleteSqlBuilder)parent;
	}
	/**
	 * 完成当前内嵌构造，返回到UpdateSqlBuilder构造
	 * @return
	 */
	public UpdateSqlBuilder toUpd()
	{
		over();
		return (UpdateSqlBuilder)parent;
	}
	/**
	 * 完成当前内嵌构造，返回到InsertSqlBuilder构造
	 * @return
	 */
	public InsertSqlBuilder toIns()
	{
		over();
		return (InsertSqlBuilder)parent;
	}
	
	private void over()
	{
		ClauseItem ret=this.build();
		if(callback!=null)
			callback.accept(ret);
	}
	
	/**
	 * 开始构建一个条件项
	 * @return
	 */
	public ClauseItem build()
	{
		if(groupNodes.empty())
			return current;
		
		if(groupNodes.peek()!=TOKEN_GROUP_END) {
			groupNodes.push(current);
		}
		
		ClauseItem result=null;
		Stack<Object> next=new Stack<>();
		Object it;
		while(!groupNodes.empty()) {
			it=groupNodes.pop();
			if(it==TOKEN_NOT) {
				result=new NotCond((ClauseItem)next.pop());
				next.push(result);
			} else if(it==TOKEN_GROUP_BEGIN) {
				groupCondition(next);
			}else {
				next.push(it);
			}
		}
		while(next.size()>1)
			groupCondition(next);
		
		if(next.empty()) return null;
		return (ClauseItem)next.pop();
	}

	private void groupCondition(Stack<Object> next)
	{
		List<ClauseItem> lsAnd=new ArrayList<>();
		List<ClauseItem> lsOr=new ArrayList<>();
		Object curr;
		while(!next.empty()) {
			curr=next.pop();
			if(curr==TOKEN_GROUP_END)
				break;
			if(!(curr instanceof ClauseItem))
				continue;
			
			lsAnd.add((ClauseItem)curr);
			if(!next.empty() && next.peek()==TOKEN_OR) {
				if(lsAnd.size()>1) {
					lsOr.add(new AndCond(lsAnd));
				}else {
					lsOr.addAll(lsAnd);
				}
				lsAnd.clear();
			}
		}
		if(lsAnd.size()>1) {
			lsOr.add(new AndCond(lsAnd));
		}else {
			lsOr.addAll(lsAnd);
		}
		lsAnd.clear();
		
		if(!lsOr.isEmpty()) {
			if(lsOr.size()==1) {
				next.push(lsOr.get(0));
			}else {
				next.push(new OrCond(lsOr));
			}
			lsOr.clear();
		}
	}
}
